package com.dh.spring.thread;

import com.dh.spring.util.LocalTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

/**
 * 线程池内部维护线程，执行线程池扩容线程和回收线程任务
 * */
public class CustomLocalThread implements Runnable {
    private static final Logger logger = LoggerFactory.getLogger(CustomLocalThread.class);
    private CustomThreadPool customThreadPool;
    private CustomTaskBlockQueue customTaskBlockQueue;
    private CustomThreadFactory customThreadFactory;
    //TODO 当前线程池内部维护线程执行状态 true表示停止 false表示运行
    public static volatile boolean isStop = true;
    private long keepAliveTime;
    private String threadName;
    private String runnableName = "内部维护线程执行单元";

    public CustomLocalThread(long keepAliveTime, CustomThreadPool customThreadPool, CustomTaskBlockQueue customTaskBlockQueue,
         CustomThreadFactory customThreadFactory, String threadPoolName) {
        this.keepAliveTime = keepAliveTime;
        this.customThreadPool = customThreadPool;
        this.customTaskBlockQueue = customTaskBlockQueue;
        this.customThreadFactory = customThreadFactory;
        this.threadName = threadPoolName;
    }

    @Override
    public void run() {
        /*try {
            logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 线程池内部维护线程已开启，将在 [ " + this.keepAliveTime + " ] 后开始执行任务......");
            TimeUnit.MILLISECONDS.sleep(keepAliveTime);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }*/

        this.isStop = false;
        logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 重置线程池内部维护线程启停状态成功 isStop = " + this.getIsStop() + " ( " + (this.getIsStop()?"已停止":"已开启") + " )");

        //TODO 循环从队列中获取任务
        while(!this.customThreadPool.isShutdown() && !Thread.currentThread().isInterrupted()) {
            //TODO 执行线程扩容回收操作
            synchronized (this) {
                //TODO 如果线程池已处于关闭，则停止当前内部维护线程
                if(this.customThreadPool.isShutdown()) {
                    logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 线程池已关闭，即将终止维护线程......");
                    //终止当前线程执行任务
                    this.shutdown();
                    return;
                }

                if(this.isShutdown()) {
                    logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 内部维护线程已终止......");
                    return;
                }

                if(threadName.equals("Runnable维护线程")) {
                    /**
                     *  TODO Runnable线程扩容与回收,线程池初始线程数量和核心线程数量一致
                     *
                     * */
                    //TODO 第一次扩容 初始线程到核心数量线程
                    if (!this.customTaskBlockQueue.getRunnableTaskBlockQueueIsEmpty() // TODO (1)、扩容前判断队列是否存在任务
                        //TODO (2)、 当队列任务排队任务数多于核心线程数量执行扩容
                        && this.customTaskBlockQueue.getRunnableTaskBlockQueueSize() >  this.customThreadPool.getCoreThreadSize()
                        //TODO (3)、线程数量扩容到核心线程数量
                        && this.customThreadPool.getActiveThreadSize() < this.customThreadPool.getCoreThreadSize()) {

                        logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 内部维护线程执行第一次Runnable线程数量扩容，当前活跃线程数 activeThreadSize = " + this.customThreadPool.getActiveThreadSize() + "......");
                        for (int i = this.customThreadPool.getActiveThreadSize(); i < this.customThreadPool.getCoreThreadSize(); i++) {
                            this.customThreadFactory.execute(this.customThreadPool, this.customTaskBlockQueue, Runnable.class);
                        }
                        logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 内部维护线程执行第一次Runnable线程数量扩容完成，当前活跃线程数 activeThreadSize = " + this.customThreadPool.getActiveThreadSize() + "......");
                    }
                    //TODO 第二次扩容 核心数量线程到最大线程
                    if (!this.customTaskBlockQueue.getRunnableTaskBlockQueueIsEmpty() // TODO (1)、扩容前判断队列是否存在任务
                        //TODO (2)、 当队列任务排队任务数多于线程池最大线程数量执行扩容
                        && this.customTaskBlockQueue.getRunnableTaskBlockQueueSize() >  this.customThreadPool.getMaxThreadSize()
                        //TODO (3)、线程数量扩容到最大核心线程数量
                        && this.customThreadPool.getActiveThreadSize() < this.customThreadPool.getMaxThreadSize()) {

                        logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 内部维护线程执行第二次Runnable线程数量扩容，当前活跃线程数 activeThreadSize = " + this.customThreadPool.getActiveThreadSize() + "......");
                        for (int i = this.customThreadPool.getActiveThreadSize(); i < this.customThreadPool.getMaxThreadSize(); i++) {
                            this.customThreadFactory.execute(this.customThreadPool, this.customTaskBlockQueue, Runnable.class);
                        }
                        logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 内部维护线程执行第二次Runnable线程数量扩容完成，当前活跃线程数 activeThreadSize = " + this.customThreadPool.getActiveThreadSize() + "......");
                    }

                    //TODO 回收线程 任务阻塞队列为空， 且当前活跃线程数量大于核心线程数量，则将线程池线程数量恢复至核心线程数
                    if (this.customTaskBlockQueue.getRunnableTaskBlockQueueIsEmpty()
                        && this.customThreadPool.getActiveThreadSize() > this.customThreadPool.getCoreThreadSize()) {

                        logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 内部维护线程执行Runnable线程回收，当前活跃线程数 activeThreadSize = " + this.customThreadPool.getActiveThreadSize() + "......");
                        for (int i = this.customThreadPool.getCoreThreadSize(); i < this.customThreadPool.getActiveThreadSize(); i++) {
                            this.customThreadFactory.removeThread(this.customThreadPool);
                        }
                        logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 内部维护线程执行Runnable线程回收结束，当前活跃线程数 activeThreadSize = " + this.customThreadPool.getActiveThreadSize() + "......");
                    }
                }

                /*if(threadName.equals("Callable维护线程")) {
                    *//*Callable线程扩容与回收 *//*
                    //TODO 第一次扩容 初始线程到核心数量线程
                    if (!this.customTaskBlockQueue.getCallableTaskBlockQueueIsEmpty()
                        && this.customTaskBlockQueue.getCallableTaskBlockQueueSize() >  this.customThreadPool.getCoreThreadSize()
                        && this.customThreadPool.getActiveThreadSize() < this.customThreadPool.getCoreThreadSize()) {

                        logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 内部维护线程执行第一次Callable线程数量扩容，当前活跃线程数 activeThreadSize = " + this.customThreadPool.getActiveThreadSize() + "......");
                        for (int i = this.customThreadPool.getActiveThreadSize(); i < this.customThreadPool.getCoreThreadSize(); i++) {
                            this.customThreadFactory.execute(this.customThreadPool, this.customTaskBlockQueue, Runnable.class);
                        }
                        logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 内部维护线程执行第一次Callable线程数量扩容完成，当前活跃线程数 activeThreadSize = " + this.customThreadPool.getActiveThreadSize() + "......");
                    }
                    //TODO 第二次扩容 核心数量线程到最大线程
                    if (!this.customTaskBlockQueue.getCallableTaskBlockQueueIsEmpty()
                        && this.customTaskBlockQueue.getCallableTaskBlockQueueSize() >  this.customThreadPool.getMaxThreadSize()
                        && this.customThreadPool.getActiveThreadSize() < this.customThreadPool.getMaxThreadSize()) {

                        logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 内部维护线程执行第二次Callable线程数量扩容，当前活跃线程数 activeThreadSize = " + this.customThreadPool.getActiveThreadSize() + "......");
                        for (int i = this.customThreadPool.getActiveThreadSize(); i < this.customThreadPool.getMaxThreadSize(); i++) {
                            this.customThreadFactory.execute(this.customThreadPool, this.customTaskBlockQueue, Runnable.class);
                        }
                        logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 内部维护线程执行第二次Callable线程数量扩容完成，当前活跃线程数 activeThreadSize = " + this.customThreadPool.getActiveThreadSize() + "......");
                    }

                    //TODO 回收线程 任务阻塞队列为空， 且当前活跃线程数量大于核心线程数量，则将线程池线程数量恢复至核心线程数
                    if (this.customTaskBlockQueue.getCallableTaskBlockQueueIsEmpty()
                        && this.customThreadPool.getActiveThreadSize() > this.customThreadPool.getCoreThreadSize()) {

                        logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 内部维护线程执行Callable线程回收，当前活跃线程数 activeThreadSize = " + this.customThreadPool.getActiveThreadSize() + "......");
                        for (int i = this.customThreadPool.getCoreThreadSize(); i < this.customThreadPool.getActiveThreadSize(); i++) {
                            this.customThreadFactory.removeThread(this.customThreadPool);
                        }
                        logger.info("[ " + LocalTime.formatDate(LocalDateTime.now()) + " ] 内部维护线程执行Callable线程回收结束，当前活跃线程数 activeThreadSize = " + this.customThreadPool.getActiveThreadSize() + "......");
                    }
                }*/
            }

        }
    }

    public void shutdown() {
        //TODO 当前内部维护线程处于运行,则中断其执行
        if(!this.isStop) {
            this.isStop = true;//运行状态重置为停止
            Thread.currentThread().interrupt();
        }
    }

    private boolean isShutdown() {
        return this.isStop;
    }

    public String getRunnableName() {
        return runnableName;
    }

    public boolean getIsStop() {
        return isStop;
    }
}
